﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace reactiveBT.BT.Blackboard
{
    /// <summary>
    /// 树事件，基于C#事件提供的一层封装，多加一层异常处理
    /// 如果直接用多播做，太不安全了
    /// </summary>
    public class TreeEvent
    {
        private Action<dynamic, dynamic, Type> onValueChangeEvent;
        public TreeEvent(Action<dynamic, dynamic, Type> onValueChange)
        {
            onValueChangeEvent += onValueChange;
        }
        public void AddListener(Action<dynamic, dynamic, Type> onValueChange)
        {
            if (onValueChangeEvent == null)
            {
                onValueChangeEvent += onValueChange;
                return;
            }
            var list = onValueChangeEvent.GetInvocationList();
            if(list.Contains(onValueChange))
            {
                Console.WriteLine("重复添加事件监听");
                return;
            }
            else
            {
                onValueChangeEvent += onValueChange;
            }
        }
        public void RemoveListener(Action<dynamic, dynamic, Type> onValueChange)
        {
            if(onValueChangeEvent == null || !onValueChangeEvent.GetInvocationList().Contains(onValueChange))
            {
                Console.WriteLine("不能删除不存在的委托事件");
            }
            onValueChangeEvent -= onValueChange;
        }
        public void RemoveAll()
        {
            if(onValueChangeEvent != null)
            {
                var delegates = onValueChangeEvent.GetInvocationList();
                for(int i = 0; i < delegates.Length; i++)
                {
                    onValueChangeEvent -= delegates[i] as Action<dynamic, dynamic, Type>;
                }
            }
        }
        public void Invoke(dynamic oldvalue,dynamic newvalue,Type type)
        {
            if(onValueChangeEvent == null)
            {
                return;
            }
            var delegatelist = onValueChangeEvent.GetInvocationList();
            foreach(Action<dynamic,dynamic,Type> dele in delegatelist)
            {
                if(dele.Target != null)
                {
                    dele.Invoke(oldvalue, newvalue, type);
                }
            }
        }
    }
}
